home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/tasks.h>
- #include <exec/ports.h>
- #include <exec/libraries.h>
- #include <exec/io.h>
- #include <exec/devices.h>
- #include <exec/errors.h>
- #include <proto/exec.h>
- #include <devices/console.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <intuition/intuition.h>
- #include <dos.h>
- #include "machdep.h"
- #include "mbuf.h"
- #include "timer.h"
- #include "internet.h"
- #include "icmp.h"
- #include "netuser.h"
- #include "tcp.h"
- #include "telnet.h"
- #include "session.h"
- #include "inetdev.h"
- #include "inetlib.h"
- #define DEBUG
- struct Process *mytask;
- APTR oldwindowptr;
- struct IntuitionBase *IntuitionBase;
- char banner[80] = "telnet window";
- static struct NewWindow nw = {
- 0, 0, 640, 200, /* left, top, (max) width, (max) height */
- 0, 1, /* detail pen, block pen */
- 0, /* IDCMP flags */
- SMART_REFRESH | WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING |
- SIZEBBOTTOM | ACTIVATE | NOCAREREFRESH, /* window flags */
- NULL, NULL, /* gadget, checkmark */
- (UBYTE *)&banner[0], /* title of window */
- NULL, NULL, /* screen, bitmap */
- 200, 50, -1, -1, /* sizing limits */
- WBENCHSCREEN, /* on the workbench */
- };
- struct Window *win;
- struct MsgPort *keyboard, *consinp, *consoutp, *tcpinp, *tcpoutp;
- struct IOStdReq consin, consout;
- char InputCharacter;
- int deviceopened = 0;
- struct IOINETReq tnreq, tninreq, tnoutreq;
- char recv[512], snd[512];
- struct telnet *tn;
- #ifdef LATTICE
- extern struct { short error; char *msg; } os_errlist[];
- extern int _OSERR, os_nerr;
- #endif
- static
- clean(why)
- char *why;
- {
- int i;
- InputCharacter = ' ';
- while (InputCharacter != '<')
- if (kbread() > 0)
- amigaputchar(InputCharacter);
-
- if (win)
- CloseWindow(win);
- if (consinp)
- DeletePort(consinp);
- if (consoutp)
- DeletePort(consoutp);
- if (tcpinp)
- DeletePort(tcpinp);
- if (tcpoutp)
- DeletePort(tcpoutp);
- if (deviceopened)
- CloseDevice(&tnreq);
- mytask->pr_WindowPtr = oldwindowptr;
- if (why) {
- myoserr(why);
- }
- exit(0);
- }
- printlist(l)
- struct List *l;
- {
- printf("head %x tail %x tailpred %x\n", l->lh_Head, l->lh_Tail,
- l->lh_TailPred);
- }
- myoserr(why)
- char *why;
- {
- int i;
- fprintf(stderr, "%s: ", why);
- #ifdef LATTICE
- fprintf(stderr, "%d: ", _OSERR);
-
- for(i = 0; os_errlist[i].error < os_nerr; i++)
- if (os_errlist[i].error == _OSERR)
- fprintf(stderr, os_errlist[i].msg);
- #endif
- fprintf(stderr, "\r\n");
- }
- /* Called at startup time to set up console I/O, memory heap */
- ioinit()
- {
- struct Screen *scr;
-
- mytask = (struct Process *) FindTask((char *) NULL);
- oldwindowptr = mytask->pr_WindowPtr;
- mytask->pr_WindowPtr = (APTR) -1; /* disable DOS requestors */
-
- if ((IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 33L)) == NULL)
- clean("No intuition: Version 1.2 of Amiga Systems Software required");
- /*
- * Try to determine the size of the workbench screen
- */
- scr = malloc(sizeof(struct Screen));
- if (scr==NULL)
- clean("Can't alloc screen");
-
- if (GetScreenData(scr, (ULONG) sizeof(struct Screen),
- WBENCHSCREEN, NULL) == TRUE) {
- nw.Width = scr->Width;
- nw.Height = scr->Height-20;
- nw.TopEdge = 19;
- } else
- fprintf(stderr, "Can't GetScreenData()\n");
-
- free((char *)scr);
- if ((win = OpenWindow(&nw)) == NULL)
- clean("Can't open window");
- if ((consinp = CreatePort("telnet:console in", 0L)) == NULL)
- clean("Can't create console port");
- if ((tcpinp = CreatePort("telnet:tcp in", 0L)) == NULL)
- clean("Can't create telnet tcp input port");
- if ((tcpoutp = CreatePort("telnet:tcp out", 0L)) == NULL)
- clean("Can't create telnet tcp output port");
-
- consin.io_Data = (APTR) win;
- consin.io_Length = sizeof(struct Window);
-
- _OSERR = OpenDevice("console.device", 0L, &consin, 0L);
- if (_OSERR != 0L){
- printf("opendevice returned %d\n", _OSERR);
- myoserr("could not get console");
- clean("Can't open console device");
- }
- consout = consin;
-
- consin.io_Message.mn_ReplyPort = consinp;
- consin.io_Length = 1;
- consin.io_Data = (APTR) &InputCharacter;
- consin.io_Command = CMD_READ;
- SendIO(&consin);
- consout.io_Message.mn_ReplyPort = consoutp;
- consout.io_Command = CMD_WRITE;
-
-
- }
- /* Read characters from the keyboard, translating them to "real" ASCII
- * If none are ready, return the -1 from kbraw()
- */
- kbread()
- {
- char c;
-
- if (CheckIO(&consin)) {
- WaitIO(&consin);
- c = InputCharacter;
- consin.io_Length = 1;
- consin.io_Data = (APTR) &InputCharacter;
- consin.io_Command = CMD_READ;
- SendIO(&consin); /* start next read up */
- return (c & 0xff);
- }
-
- return -1; /* nuthin here */
- }
- extern char nospace[];
- int refuse_echo = 0;
- int unix_line_mode = 0; /* if true turn <cr> to <nl> when in line mode */
-
- #ifdef DEBUG
- char *t_options[] = {
- "Transmit Binary",
- "Echo",
- "",
- "Suppress Go Ahead",
- "",
- "Status",
- "Timing Mark"
- };
- #endif
- /* Telnet receiver upcall routine */
- void
- rcv_char()
- {
- /*printf("rcv_char: %d\n", tninreq.io_Actual);*/
- tel_input(tn,tninreq.io_Data, tninreq.io_Actual);
-
- fflush(stdout);
- }
- brk()
- {
- clean("ok i iwll quit\n");
- }
- /* TCP connection states */
- char *tcpstates[] = {
- "Closed",
- "Listen",
- "SYN sent",
- "SYN received",
- "Established",
- "FIN wait 1",
- "FIN wait 2",
- "Close wait",
- "Closing",
- "Last ACK",
- "Time wait"
- };
- /* TCP segment header flags */
- char *tcpflags[] = {
- "FIN", /* 0x01 */
- "SYN", /* 0x02 */
- "RST", /* 0x04 */
- "PSH", /* 0x08 */
- "ACK", /* 0x10 */
- "URG" /* 0x20 */
- };
-
- /* TCP closing reasons */
- char *reasons[] = {
- "Normal",
- "Reset",
- "Timeout",
- "ICMP"
- };
- char old = LISTEN;
- int done = 0;
- char *hostname="";
- int hostport=0;
- char *bannerfmt = "telnet %10s %4d %10s";
- void
- showstate(old, new)
- char old, new;
- {
-
-
- /* extern char *tcpstates[];
- extern char *reasons[];
- extern char *unreach[];
- extern char *exceed[];
- */
- /* Can't add a check for unknown connection here, it would loop
- * on a close upcall! We're just careful later on.
- */
-
- sprintf(banner, bannerfmt, hostname, hostport, tcpstates[new]);
- SetWindowTitles(win, banner, -1);
- switch(new){
- case CLOSE_WAIT:
- done = 1;
- break;
- case CLOSED: /* court adjourned */
- /* printf("%s (%s",tcpstates[new],reasons[tcb->reason]);
- if(tcb->reason == NETWORK){
- switch(tcb->type){
- case DEST_UNREACH:
- printf(": %s unreachable",unreach[tcb->code]);
- break;
- case TIME_EXCEED:
- printf(": %s time exceeded",exceed[tcb->code]);
- break;
- }
- }
- printf(")\r\n");
- */
- done = 1;
- break;
- default:
- break;
- }
- fflush(stdout);
-
- }
-
- /* Execute user telnet command */
- main(argc,argv)
- int argc;
- char *argv[];
- {
- extern int _OSERR;
- struct InternetBase *InternetBase;
- int send_tel();
- int unix_send_tel();
- struct session *s;
-
- /* struct tcb *tcb = NULL;*/
- struct socket lsocket,fsocket;
- ioinit();
- hostname = argv[1];
- old = LISTEN;
- showstate(old, LISTEN);
- tnreq.io_fsocket.address = aton(argv[1]);
- if(argc < 3)
- tnreq.io_fsocket.port = TELNET_PORT;
- else
- tnreq.io_fsocket.port = atoi(argv[2]);
- tnreq.io_Device = NULL;
- tnreq.io_Unit = NULL;
- tnreq.io_Flags = 0;
- tnreq.io_Error = 0;
- InternetBase = (struct InternetBase *) OpenDevice("internet.device",
- (long) INET_UNIT_TCP, &tnreq, 0L);
- if (InternetBase != 0L){
- printf("it did not open %d\n",InternetBase);
- clean("i quit");
- }
- /* tcb = (struct tcb *) tnreq.io_Unit->iu_ccb;*/
-
- hostport = tnreq.io_lsocket.port;
- deviceopened = 1;
- tninreq = tnreq; /* possible lettuce bug ?*/
- tnoutreq = tnreq;
- tninreq.io_Length = 512;
- tnoutreq.io_Length = 1;
- tninreq.io_Data = recv;
- tnoutreq.io_Data = &InputCharacter;
- tninreq.io_Command = CMD_READ;
- tnoutreq.io_Command = CMD_WRITE;
- tninreq.io_Message.mn_ReplyPort = tcpinp;
- tnoutreq.io_Message.mn_ReplyPort = tcpoutp;
- /* Create and initialize a Telnet protocol descriptor */
- if((tn = (struct telnet *)calloc(1,sizeof(struct telnet))) == NULLTN){
- myoserr("calloc faiuled\n");
- goto done;
- }
- tn->session = s; /* Upward pointer */
- tn->state = TS_DATA;
- SendIO(&tninreq);
- onbreak(&brk);
- InputCharacter = ' ';
- while (! done)
- {
- if ((snd[0] = kbread()) >= 0){
-
- unix_send_tel(snd, (short) 1);}
-
- if (CheckIO(&tninreq))
- {
- chkabort();
- WaitIO(&tninreq);
- rcv_char();
- if (tninreq.io_State != old)
- {
- showstate(old, tninreq.io_State);
- old = tninreq.io_State;
- }
- SendIO(&tninreq);
- }
- }
- done:
- clean("All done");
-
- #ifdef NOTDEF
- /* Allocate a session descriptor */
- if((s = newsession()) == NULLSESSION){
- printf("Too many sessions\r\n");
- return 1;
- }
- s->type = TELNET;
- if ((refuse_echo == 0) && (unix_line_mode != 0)) {
- s->parse = unix_send_tel;
- } else {
- s->parse = send_tel;
- }
- current = s;
-
- /* Create and initialize a Telnet protocol descriptor */
- if((tn = (struct telnet *)calloc(1,sizeof(struct telnet))) == NULLTN){
- printf(nospace);
- s->type = FREE;
- return 1;
- }
- tn->session = s; /* Upward pointer */
- tn->state = TS_DATA;
- s->cb.telnet = tn; /* Downward pointer */
-
- tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,0,
- rcv_char,NULLVFP,t_state,0,(int *)tn);
- if(tcb == NULLTCB || tcb->state == CLOSED){
- /* This is actually a bit dirty here. About the only time the
- * state will be closed here is if we tried to connect to
- * ourselves and got RST'ed. If this is true then the close
- * upcall will already have freed the TCB and telnet block,
- * so we're looking at the TCB after it's back on the heap.
- */
- return 0;
- }
- tn->tcb = tcb; /* Downward pointer */
- go();
- return 0;
- #endif
- }
-
- /* Process typed characters */
- int
- unix_send_tel(buf,n)
- char *buf;
- int16 n;
- {
- int i;
- /*printf("unix_send_tel: buf[0] %d\n", buf[0]);*/
- for (i=0; (i<n) && (buf[i] != '\r'); i++)
- ;
- if (buf[i] == '\r') {
- buf[i] = '\n';
- n = i+1;
- }
- send_tel(buf,n);
- }
- int
- send_tel(buf,n)
- char *buf;
- int16 n;
- {
- int i;
-
- tnoutreq.io_Data = buf;
- tnoutreq.io_Length = n;
-
- SendIO(&tnoutreq);
- /* printf("now waitio insend_tel: ");*/
- i = WaitIO(&tnoutreq);
- /*printf("send_tel: WaitIo is %d\n", i);*/
- if (tnoutreq.io_State != old)
- {
- showstate(old, tnoutreq.io_State);
- old = tnoutreq.io_State;
- }
-
- }
-
- /* Process incoming TELNET characters */
- int
- tel_input(tn,bp, len)
- register struct telnet *tn;
- char *bp;
- int len;
- {
- char c;
- int ci;
- void doopt(),dontopt(),willopt(),wontopt(),answer();
- #ifdef FAST /* DON'T USE -- Aztec memchr() routine is broken */
- char *memchr();
-
- /* Optimization for very common special case -- no command chars */
- if(tn->state == TS_DATA){
- while(bp != NULLBUF && memchr(bp->data,IAC,bp->cnt)
- == NULLCHAR){
- fflush(stdout);
- write(1,bp->data,bp->cnt);
- bp = free_mbuf(bp);
- }
- }
- #endif
- while(len--){
- c = *bp++;
- ci = c & 0xff;
- switch(tn->state){
- case TS_DATA:
- if(ci == IAC){
- tn->state = TS_IAC;
- } else {
- if(!tn->remote[TN_TRANSMIT_BINARY])
- c &= 0x7f;
- putchar(c);
- }
- break;
- case TS_IAC:
- switch(ci){
- case WILL:
- tn->state = TS_WILL;
- break;
- case WONT:
- tn->state = TS_WONT;
- break;
- case DO:
- tn->state = TS_DO;
- break;
- case DONT:
- tn->state = TS_DONT;
- break;
- case IAC:
- putchar(c);
- tn->state = TS_DATA;
- break;
- default:
- tn->state = TS_DATA;
- break;
- }
- break;
- case TS_WILL:
- willopt(tn,ci);
- tn->state = TS_DATA;
- break;
- case TS_WONT:
- wontopt(tn,ci);
- tn->state = TS_DATA;
- break;
- case TS_DO:
- doopt(tn,ci);
- tn->state = TS_DATA;
- break;
- case TS_DONT:
- dontopt(tn,ci);
- tn->state = TS_DATA;
- break;
- }
- }
- }
-
- #ifdef NOTDEF
- /* State change upcall routine */
- void
- t_state(tcb,old,new)
- register struct tcb *tcb;
- char old,new;
- {
- struct telnet *tn;
- char notify = 0;
- extern char *tcpstates[];
- extern char *reasons[];
- extern char *unreach[];
- extern char *exceed[];
-
- /* Can't add a check for unknown connection here, it would loop
- * on a close upcall! We're just careful later on.
- */
- tn = (struct telnet *)tcb->user;
-
- if(current != NULLSESSION && current->type == TELNET && current->cb.telnet == tn)
- notify = 1;
-
- switch(new){
- case CLOSE_WAIT:
- if(notify)
- printf("%s\r\n",tcpstates[new]);
- close_tcp(tcb);
- break;
- case CLOSED: /* court adjourned */
- if(notify){
- printf("%s (%s",tcpstates[new],reasons[tcb->reason]);
- if(tcb->reason == NETWORK){
- switch(tcb->type){
- case DEST_UNREACH:
- printf(": %s unreachable",unreach[tcb->code]);
- break;
- case TIME_EXCEED:
- printf(": %s time exceeded",exceed[tcb->code]);
- break;
- }
- }
- printf(")\r\n");
- cmdmode();
- }
- del_tcp(tcb);
- if(tn != NULLTN)
- free_telnet(tn);
- break;
- default:
- if(notify)
- printf("%s\r\n",tcpstates[new]);
- break;
- }
- fflush(stdout);
- }
- #endif
- /* Delete telnet structure */
- static
- free_telnet(tn)
- struct telnet *tn;
- {
-
- if(tn != NULLTN)
- free((char *)tn);
- }
-
- /* The guts of the actual Telnet protocol: negotiating options */
- static
- void
- willopt(tn,opt)
- struct telnet *tn;
- int opt;
- {
- int ack;
- void answer();
-
- #ifdef DEBUG
- printf("recv: will ");
- if(opt <= NOPTIONS)
- printf("%s\r\n",t_options[opt]);
- else
- printf("%u\r\n",opt);
- #endif
-
- switch(opt){
- case TN_TRANSMIT_BINARY:
- case TN_ECHO:
- case TN_SUPPRESS_GA:
- if(tn->remote[opt] == 1)
- return; /* Already set, ignore to prevent loop */
- if(opt == TN_ECHO){
- if(refuse_echo){
- /* User doesn't want to accept */
- ack = DONT;
- break;
- } else
- raw(); /* Put tty into raw mode */
- }
- tn->remote[opt] = 1;
- ack = DO;
- break;
- default:
- ack = DONT; /* We don't know what he's offering; refuse */
- }
- answer(tn,ack,opt);
- }
- static
- void
- wontopt(tn,opt)
- struct telnet *tn;
- int opt;
- {
- void answer();
-
- #ifdef DEBUG
- printf("recv: wont ");
- if(opt <= NOPTIONS)
- printf("%s\r\n",t_options[opt]);
- else
- printf("%u\r\n",opt);
- #endif
- if(opt <= NOPTIONS){
- if(tn->remote[opt] == 0)
- return; /* Already clear, ignore to prevent loop */
- tn->remote[opt] = 0;
- if(opt == TN_ECHO)
- cooked(); /* Put tty into cooked mode */
- }
- answer(tn,DONT,opt); /* Must always accept */
- }
- static
- void
- doopt(tn,opt)
- struct telnet *tn;
- int opt;
- {
- void answer();
- int ack;
-
- #ifdef DEBUG
- printf("recv: do ");
- if(opt <= NOPTIONS)
- printf("%s\r\n",t_options[opt]);
- else
- printf("%u\r\n",opt);
- #endif
- switch(opt){
- #ifdef FUTURE /* Use when local options are implemented */
- if(tn->local[opt] == 1)
- return; /* Already set, ignore to prevent loop */
- tn->local[opt] = 1;
- ack = WILL;
- break;
- #endif
- default:
- ack = WONT; /* Don't know what it is */
- }
- answer(tn,ack,opt);
- }
- static
- void
- dontopt(tn,opt)
- struct telnet *tn;
- int opt;
- {
- void answer();
-
- #ifdef DEBUG
- printf("recv: dont ");
- if(opt <= NOPTIONS)
- printf("%s\r\n",t_options[opt]);
- else
- printf("%u\r\n",opt);
- #endif
- if(opt <= NOPTIONS){
- if(tn->local[opt] == 0){
- /* Already clear, ignore to prevent loop */
- return;
- }
- tn->local[opt] = 0;
- }
- answer(tn,WONT,opt);
- }
- static
- void
- answer(tn,r1,r2)
- struct telnet *tn;
- int r1,r2;
- {
- struct mbuf *bp,*qdata();
- char s[3];
-
- #ifdef DEBUG
- switch(r1){
- case WILL:
- printf("sent: will ");
- break;
- case WONT:
- printf("sent: wont ");
- break;
- case DO:
- printf("sent: do ");
- break;
- case DONT:
- printf("sent: dont ");
- break;
- }
- if(r2 <= 6)
- printf("%s\r\n",t_options[r2]);
- else
- printf("%u\r\n",r2);
- #endif
-
- s[0] = IAC;
- s[1] = r1;
- s[2] = r2;
- tnoutreq.io_Data = s;
- tnoutreq.io_Length = 3;
- DoIO(&tnoutreq);
- /*
- bp = qdata(s,(int16)3);
- send_tcp(tn->tcb,bp);
- */
- }
-
- #define BUFMAXCNT 150
- static char conbuf[BUFMAXCNT];
- static int concnt = 0;
-
- int
- amigaputchar(c)
- char c;
- {
- conbuf[concnt++] = c;
- if ((c == '\n') || (concnt == BUFMAXCNT))
- amigaflush();
- return c;
- }
-
- amigaflush()
- {
- if (concnt == 0)
- return;
- consout.io_Data = (APTR) conbuf;
- consout.io_Length = concnt;
- consout.io_Command = CMD_WRITE;
- DoIO(&consout);
- concnt = 0;
- }
-
- /*
- * Begin terrible, horrible hack. All output should be printed upon (into?)
- * the window we opened before. Here goes nothing...
- */
-
- printf(a, b, c, d, e, f, g, h, i, j, k)
- char *a;
- int b, c, d, e, f, g, h, i, j, k;
- {
- if (concnt)
- amigaflush();
-
- sprintf(conbuf, a, b, c, d, e, f, g, h, i, j, k);
- consout.io_Data = (APTR) conbuf;
- consout.io_Length = strlen(conbuf);
- consout.io_Command = CMD_WRITE;
- DoIO(&consout); /* no use in doing this async */
- }
-